

#include "websocket.h"

#include <ArduinoJson.h>
#include "ActionCtrl.h"
#include "utils.h"
#include "config.h"
#include "websocket/ArduinoWebsockets.h"
#include "mainfunc.h"
#include "global.h"
#include "Log.h"

using namespace websockets;
WebsocketsClient wsclient;

bool isWsconnectVal = false;
bool isNeedConnectWsVal = false;

void reConnectWS(String s)
{
    int i = s.toInt();
    if (i % 20 == 0)
    {
        if (!isWsconnect())
        {

            //  connectWS();
            setNeedConnectWs(true);
        }
    }
}

void sendPingCallBack(String i)
{

    // printStr("sendPingCallBack");
    if (i.toInt() % 25 == 0)
    {
        // printStr("sendping");
        setSendPing(true);
    }
}

void setNeedConnectWs(bool b)
{
    isNeedConnectWsVal = b;
}
bool isNeedConnectWs()
{
    return isNeedConnectWsVal;
}

void setupWS()
{
    addGlobalTimerCallBack("connectWs", reConnectWS);
    addGlobalTimerCallBack("ping", sendPingCallBack);
}

void sendResCode(int code, int result, String msg)
{
    Serial.println("sendResCode...");
    StaticJsonDocument<512> doc;
    doc["topic"] = "res";
    doc["code"] = code;
    doc["result"] = result;
    doc["msg"] = msg;
    doc["deviceId"] = getEspId();
    char json[512];
    serializeJson(doc, json, sizeof(json));
    printStr("发送的响应消息：", String(json));
    bool b = wsclient.send(json);
    if (b)
    {
        printStr("发送ResCode成功");
    }
    else
    {
        printStr("发送ResCode失败");
    }
}

void onMessageCallback(WebsocketsMessage message)
{
    Serial.print("Got Message: ");
    Serial.println(message.data());
    if (message.data().equals("CONNECT_SUCCESS"))
    {
        printStr("CONNECT_SUCCESS");
        return;
    }

    StaticJsonDocument<512> doc; // 假设消息不会超过512字节
    DeserializationError error = deserializeJson(doc, message.data());
    if (error)
    {
        Serial.print("deserializeJson() failed: ");
        Serial.println(error.c_str());
        return;
    }

    if (doc.containsKey("code"))
    {
        int code = doc["code"];
        if (code == CODE_PUMP_ON) // 开启水泵
        {
            int time = doc["time"];
           // pumpTimeContinue(time);
            pumpTime(time);
            String s1 = "水泵已开启，最长";
            String s2 = String(getTotalPumpTime());

            String s3 = String("秒后关闭");
            String s = s1 + s2 + s3;
            sendResCode(code, 200, s);
            beepMS(100);
            return;
        }
        else if (code == CODE_PUMP_OFF) // 关闭水泵
        {
           //setPumpContinue(false);
            setPumpStop(true);
            sendResCode(code, 200, "水泵已关闭");
            beepMS(50);
            return;
        }
        else if (code == CODE_POWER_OFF) // 关机
        {
            int time = 0;
            if (doc.containsKey("time"))
            {
                time = doc["time"];
            }
            if (time == 0)
            {
                sendResCode(code, 200, "已关机");
                beepMS(500);
                setSleepMode(GPIO_MODE);
                startSleep(1);
            }
            else
            {
                String s1 = String("已定时关机,");
                s1.concat(String(time));
                s1.concat("后唤醒");
                sendResCode(code, 200, s1);
                beepMS(500);
                setSleepMode(GPIO_TIMER_MODE);
                startSleep(1);
            }

            return;
        }
        else if (code == CODE_UPDATE_CONFIG)
        {
            printStr("请求发送数据更新");
            setSendData(true);
            sendResCode(code, 200, "设置成功");
            beepMS(10);
            return;
        }
    }
    else
    {
        // 处理缺少 "data" 或 "switch" 键的情况
        Serial.println("Missing 'data' or 'switch' field in JSON.");
    }
}

void onEventsCallback(WebsocketsEvent event, String data)
{
    if (event == WebsocketsEvent::ConnectionOpened)
    {
        Serial.println("Connnection Opened");
    }
    else if (event == WebsocketsEvent::ConnectionClosed)
    {
        Serial.println("Connnection Closed");
        setWsconnect(false);
    }
    else if (event == WebsocketsEvent::GotPing)
    {
        Serial.println("Got a Ping!");
    }
    else if (event == WebsocketsEvent::GotPong)
    {
        Serial.println("Got a Pong!");
    }
}

bool disconnectWS(){
       removeGlobalFuncCallBack("connectWs");
       removeGlobalFuncCallBack("ping");
       if(wsclient.available()){
            wsclient.close();
       }
     
      setWsconnect(false);
      return true;
}

bool connectWS()
{

    if (!isWiFiConnected())
    {
        return false;
    }
    if (wsclient.available())
    {
        return true;
    }
   // disconnectWS();
    wsclient.close();
    addGlobalTimerCallBack("connectWs", reConnectWS);
    addGlobalTimerCallBack("ping", sendPingCallBack);
    wsclient.onMessage(onMessageCallback);
    wsclient.onEvent(onEventsCallback);
    // Connect to server
    const char *websockets_server_host = WS_SERVER_URL.c_str(); // Enter server adress
    const uint16_t websockets_server_port = PORT.toInt();       // Enter server port
    Serial.println(websockets_server_host);
    Serial.println(websockets_server_port);

    bool isconnect = wsclient.connect(websockets_server_host, websockets_server_port, "/websocket/" + getEspId());

    if (isconnect)
    {
        Serial.println("ws connect!");
        setWsconnect(true);
        sendPing();
        return true;
    }
    else
    {
        Serial.println("ws not connect!");
        setWsconnect(false);
        setSendDataFailed(true);
        return false;
    }
}

void sendPing()
{
    // if (isAdvertising())
    // {
    //     return;
    // }
    if (!isWiFiConnected() || !isWsconnect())
    {
        return;
    }
    if (wsclient.send("ping"))
    {
        printStr("发送ping成功");
        setWsconnect(true);
        setSendDataFailed(false);
    }
    else
    {
        printStr("发送ping失败");
        setWsconnect(false);
        setSendDataFailed(true);
        putLog(PING_FAIL,getRtcTime().getEpoch(),"");
    }
}

void loopWS()
{

    if (isNeedConnectWs())
    {
        if (connectWS())
        {
            setNeedConnectWs(false);
        }
        else
        {
            setNeedConnectWs(true);
        }
    }

    if (!isWiFiConnected())
    {
        return;
    }

    wsclient.poll();
}

void sendWS(String msg)
{
    // if (isAdvertising())
    // {
    //     return;
    // }
    if (!isWiFiConnected() || !isWsconnect())
    {
        return;
    }
    if (wsclient.available())
    {
        bool b = wsclient.send(msg);
        setSendDataFailed(!b);
    }
}

bool isWsconnect()
{
    return isWsconnectVal;
}
void setWsconnect(bool b)
{
    isWsconnectVal = b;
}